package cn.ubest.mvvmcore.utils

import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 协程帮助类，开启协程
 * Created by maoqi on 2020/11/6.
 */
class CoroutineUtils private constructor(private val scope: CoroutineScope) {

    companion object {
        fun with(): CoroutineUtils {
            return CoroutineUtils(GlobalScope)
        }

        fun with(scope: CoroutineScope): CoroutineUtils {
            return CoroutineUtils(scope)
        }
    }

    /**
     * 使用协程执行代码块
     */
    fun execute(
        context: CoroutineContext = EmptyCoroutineContext,
        block: suspend (CoroutineScope) -> Unit
    ) {
        scope.launch(context) {
            block(this)
        }
    }

    /**
     * 在主线程开启协程
     */
    fun executeOnMain(block: suspend (CoroutineScope) -> Unit) {
        execute(Dispatchers.Main, block)
    }

    /**
     * 在IO线程开启协程
     */
    fun executeOnIO(block: suspend (CoroutineScope) -> Unit) {
        execute(Dispatchers.IO, block)
    }

    /**
     * 并发请求
     */
    suspend fun <T, R> merge(
        deferred1: Deferred<T>,
        deferred2: Deferred<R>,
        handler: (t: T, r: R) -> Unit
    ) {
        val await1 = deferred1.await()
        val await2 = deferred2.await()
        if (await1 != null && await2 != null) {
            handler(await1, await2)
        }
    }

    /**
     * 并发请求
     */
    suspend fun <T, R, F> merge(
        deferred1: Deferred<T>,
        deferred2: Deferred<R>,
        deferred3: Deferred<F>,
        handler: (t: T, r: R, f: F) -> Unit
    ) {
        val await1 = deferred1.await()
        val await2 = deferred2.await()
        val await3 = deferred3.await()
        if (await1 != null && await2 != null && await3 != null) {
            handler(await1, await2, await3)
        }
    }
}